using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

class TestDnsServerName
{
    static async Task Main()
    {
        try
        {
            Console.WriteLine("=== DNS服务器名测试程序 ===");
            
            // 创建DNS查询数据包
            var query = CreateDnsQuery("google.com");
            
            // 发送到本地DNS服务
            using var udpClient = new UdpClient();
            var serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 153);
            
            Console.WriteLine($"发送DNS查询到 127.0.0.1:153");
            await udpClient.SendAsync(query, query.Length, serverEndPoint);
            
            // 接收响应
            var receiveTask = udpClient.ReceiveAsync();
            var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5));
            
            var completedTask = await Task.WhenAny(receiveTask, timeoutTask);
            
            if (completedTask == receiveTask)
            {
                var response = receiveTask.Result;
                Console.WriteLine($"收到DNS响应，长度: {response.Buffer.Length} 字节");
                
                // 解析响应头部
                ParseDnsResponse(response.Buffer);
                
                // 解析响应
                var ipAddress = ExtractIpFromDnsResponse(response.Buffer);
                if (!string.IsNullOrEmpty(ipAddress))
                {
                    Console.WriteLine($"DNS查询成功: google.com -> {ipAddress}");
                }
                else
                {
                    Console.WriteLine("DNS响应解析失败");
                }
            }
            else
            {
                Console.WriteLine("DNS查询超时");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"测试失败: {ex.Message}");
        }
        
        Console.WriteLine("按任意键退出...");
        Console.ReadKey();
    }
    
    static byte[] CreateDnsQuery(string domain)
    {
        var query = new System.Collections.Generic.List<byte>();
        
        // 事务ID (随机)
        var random = new Random();
        query.Add((byte)random.Next(0, 256));
        query.Add((byte)random.Next(0, 256));
        
        // 标志：标准查询，递归查询
        query.Add(0x01); // QR=0, OPCODE=0, AA=0, TC=0, RD=1
        query.Add(0x00); // RA=0, Z=0, RCODE=0
        
        // 问题数量 = 1
        query.Add(0x00);
        query.Add(0x01);
        
        // 回答数量 = 0
        query.Add(0x00);
        query.Add(0x00);
        
        // 权威记录数量 = 0
        query.Add(0x00);
        query.Add(0x00);
        
        // 附加记录数量 = 0
        query.Add(0x00);
        query.Add(0x00);
        
        // 域名部分
        var domainParts = domain.Split('.');
        foreach (var part in domainParts)
        {
            query.Add((byte)part.Length);
            query.AddRange(Encoding.UTF8.GetBytes(part));
        }
        query.Add(0x00); // 域名结束
        
        // 查询类型 A记录 = 1
        query.Add(0x00);
        query.Add(0x01);
        
        // 查询类 IN = 1
        query.Add(0x00);
        query.Add(0x01);
        
        return query.ToArray();
    }
    
    static void ParseDnsResponse(byte[] responseData)
    {
        if (responseData.Length < 12) return;
        
        Console.WriteLine($"=== DNS响应头部分析 ===");
        
        // 事务ID
        var transactionId = (responseData[0] << 8) | responseData[1];
        Console.WriteLine($"事务ID: 0x{transactionId:X4}");
        
        // 标志
        var flags1 = responseData[2];
        var flags2 = responseData[3];
        
        var qr = (flags1 & 0x80) != 0 ? "响应" : "查询";
        var opcode = (flags1 & 0x78) >> 3;
        var aa = (flags1 & 0x04) != 0 ? "是" : "否";
        var tc = (flags1 & 0x02) != 0 ? "是" : "否";
        var rd = (flags1 & 0x01) != 0 ? "是" : "否";
        
        var ra = (flags2 & 0x80) != 0 ? "是" : "否";
        var rcode = flags2 & 0x0F;
        
        Console.WriteLine($"QR (查询/响应): {qr}");
        Console.WriteLine($"OPCODE: {opcode}");
        Console.WriteLine($"AA (权威应答): {aa}");
        Console.WriteLine($"TC (截断): {tc}");
        Console.WriteLine($"RD (递归期望): {rd}");
        Console.WriteLine($"RA (递归可用): {ra}");
        Console.WriteLine($"RCODE (响应码): {rcode}");
        
        // 记录数量
        var qdcount = (responseData[4] << 8) | responseData[5];
        var ancount = (responseData[6] << 8) | responseData[7];
        var nscount = (responseData[8] << 8) | responseData[9];
        var arcount = (responseData[10] << 8) | responseData[11];
        
        Console.WriteLine($"问题数量: {qdcount}");
        Console.WriteLine($"回答数量: {ancount}");
        Console.WriteLine($"权威记录数量: {nscount}");
        Console.WriteLine($"附加记录数量: {arcount}");
        
        Console.WriteLine($"=== 响应分析完成 ===");
    }
    
    static string? ExtractIpFromDnsResponse(byte[] responseData)
    {
        try
        {
            if (responseData.Length < 12) return null;
            
            // 检查响应码
            var rcode = responseData[3] & 0x0F;
            if (rcode != 0) return null; // 非零表示错误
            
            // 获取回答数量
            var answerCount = (responseData[6] << 8) | responseData[7];
            if (answerCount == 0) return null;
            
            // 跳过问题部分
            int position = 12;
            while (position < responseData.Length && responseData[position] != 0)
            {
                int length = responseData[position];
                position += length + 1;
            }
            position += 5; // 跳过结束的0和QType、QClass
            
            // 查找A记录
            for (int i = 0; i < answerCount && position < responseData.Length - 10; i++)
            {
                // 跳过域名指针（2字节）
                if (responseData[position] == 0xC0)
                {
                    position += 2;
                }
                else
                {
                    // 跳过域名
                    while (position < responseData.Length && responseData[position] != 0)
                    {
                        int length = responseData[position];
                        position += length + 1;
                    }
                    position++; // 跳过结束的0
                }
                
                // 检查记录类型
                var type = (responseData[position] << 8) | responseData[position + 1];
                position += 2;
                
                // 跳过类
                position += 2;
                
                // 跳过TTL
                position += 4;
                
                // 获取数据长度
                var dataLength = (responseData[position] << 8) | responseData[position + 1];
                position += 2;
                
                if (type == 1 && dataLength == 4) // A记录，IPv4地址
                {
                    // 提取IP地址
                    var ipBytes = responseData[position..(position + 4)];
                    return new IPAddress(ipBytes).ToString();
                }
                
                position += dataLength;
            }
        }
        catch (Exception)
        {
            return null;
        }
        
        return null;
    }
}